package com.cloud.poetry.chatroom.component;

import com.alibaba.fastjson.JSON;
import com.cloud.poetry.base.entity.po.ChatLog;
import com.cloud.poetry.base.feign.SystemFeignClient;
import com.cloud.poetry.core.constant.StateConstant;
import com.cloud.poetry.core.entity.ChatCacheUser;
import com.cloud.poetry.core.entity.MsgBody;
import com.cloud.poetry.core.util.SpringContextUtils;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import javax.websocket.*;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.time.LocalDateTime;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.Collectors;

/**
 * @author mengxj
 */
@ServerEndpoint("/socket/{uid}")
@Component
@Slf4j
public class ChatRoomServer {

    private static final Map<Long, Session> SESSION_CACHE = new ConcurrentHashMap<>();

    private static final Map<Long, ChatCacheUser> USER_CACHE = new ConcurrentHashMap<>();

    @OnOpen
    public void onOpen(Session session, @PathParam("uid") Long uid) {
        this.sendOnlineOrClose(StateConstant.ON_OPEN, uid);
        SESSION_CACHE.put(uid, session);
    }

    @OnMessage
    public void onMessage(String message) {
        MsgBody body = MsgBody.parseBody(message);
        this.sendMessage(body.getFrom(), body.getTo(), body.getMessage());
    }

    @OnClose
    public void onClose(@PathParam("uid") Long uid) {
        SESSION_CACHE.remove(uid);
        this.sendOnlineOrClose(StateConstant.ON_CLOSE, uid);
        USER_CACHE.remove(uid);
    }

    @OnError
    public void onError(Throwable throwable){
        System.out.println("发生错误");
        throwable.printStackTrace();
    }

    private void sendOnlineOrClose(int code, Long from){
        SESSION_CACHE.forEach((k, v) -> {
            if(!k.equals(from)){
                MsgBody body = MsgBody.sendBody(code, from, k, null);
                this.sendMessage(v, body);
            }
        });
        MsgBody body = MsgBody.sendBody(StateConstant.ON_OPEN, from, null, "上线");
        body.setFromName(this.getUsername(from));
        this.saveChatLog(body);
    }

    private void sendMessage(Long from, Long to, String message){
        MsgBody body = MsgBody.sendBody(StateConstant.ON_MESSAGE, from, to, message);
        Session session = SESSION_CACHE.get(to);
        this.sendMessage(session, body);
        this.saveChatLog(body);
    }

    @SneakyThrows
    private void sendMessage(Session session, MsgBody body) {
        body.setFromName(this.getUsername(body.getFrom()));
        body.setToName(this.getUsername(body.getTo()));
        session.getBasicRemote().sendText(JSON.toJSONString(body));
    }

    private String getUsername(Long uid){
        if(Objects.isNull(uid)){
            return "";
        }
        ChatCacheUser cacheUser = USER_CACHE.get(uid);
        if(Objects.isNull(cacheUser)){
            return "";
        }
        return cacheUser.getUsername();
    }

    private void saveChatLog(MsgBody body){
        ChatLog chatLog = new ChatLog();
        chatLog.setStatus(body.getCode());
        chatLog.setFromId(body.getFrom());
        chatLog.setFromName(body.getFromName());
        chatLog.setToId(body.getTo());
        chatLog.setToName(body.getToName());
        chatLog.setMessage(body.getMessage());
        chatLog.setSendTime(LocalDateTime.now().toString());
        SystemFeignClient client = SpringContextUtils.getBean(SystemFeignClient.class);
        client.saveChatLog(chatLog);
    }

    public int getOnlineNum() {
        return USER_CACHE.values().size() - 1;
    }

    public void addUser(ChatCacheUser user) {
        USER_CACHE.put(user.getId(), user);
    }

    public List<ChatCacheUser> onlineList(Long uid) {
        return USER_CACHE.values().stream().filter(user -> !user.getId().equals(uid)).collect(Collectors.toList());
    }
}
